package com.example.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * @author ChenXiaoBin
 * on 2019-12-20
 */
public class DateWrap {

    private static final Calendar CALENDAR = Calendar.getInstance();

    public static final String FORMAT_YEAR = "yyyy";

    public static final String FORMAT_MONTH = "MM";

    public static final String FORMAT_DATE = "dd";

    public static final String FORMAT_HOUR = "HH";

    public static final String FORMAT_MINUTE = "mm";

    public static final String FORMAT_SECOND = "ss";

    public static final String DATE_FORMAT = "yyyy-MM-dd";

    public static final String TIME_FORMAT = "HH:mm:ss";

    public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";



    /**
     * 取得日期及时间，并格式化返回
     *
     * @param date 日期
     * @return 格式化日期
     */
    public static String getDateTimeFormat(Date date) {
        return format(date, DATETIME_FORMAT);
    }

    /**
     * 取得日期，并格式化返回
     *
     * @param date 日期
     * @return 格式化日期
     */
    public static String getDateFormat(Date date) {
        return format(date, DATE_FORMAT);
    }

    /**
     * 取得时间，并格式化返回
     *
     * @param date 日期
     * @return 格式化日期
     */
    public static String getTimeFormat(Date date) {
        return format(date, TIME_FORMAT);
    }

    /**
     * 取得日期的year
     *
     * @param date 日期
     * @return 格式化日期
     */
    public static Integer getYear(Date date) {
        CALENDAR.clear();
        CALENDAR.setTime(date);
        return CALENDAR.get(Calendar.YEAR);
    }

    /**
     * 取得日期的month
     *
     * @param date 日期
     * @return 格式化日期
     */
    public static Integer getMonth(Date date) {
        CALENDAR.clear();
        CALENDAR.setTime(date);
        return CALENDAR.get(Calendar.MONTH);
    }

    /**
     * 取得日期的date
     *
     * @param date 日期
     * @return 格式化日期
     */
    public static Integer getDate(Date date) {
        CALENDAR.clear();
        CALENDAR.setTime(date);
        return CALENDAR.get(Calendar.DATE);
    }


    /**
     * 取得该月份的总天数
     *
     * @param year  年份
     * @param month 月份
     * @return 天数
     */
    public static Integer getDayCountOfMonth(Integer year, Integer month) {
        Date date = parse(year + "-" + month + "-01", "yyyy-MM-dd");
        assert date != null;
        CALENDAR.clear();
        CALENDAR.setTime(date);
        return CALENDAR.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 取得该月份的总天数
     *
     * @param date 日期
     * @return 天数
     */
    public static Integer getDayCountOfMonth(Date date) {
        return getDayCountOfMonth(getYear(date), getMonth(date));
    }

    /**
     * 取得日期的月份中第几天
     *
     * @param date 日期
     * @return 第几天
     */
    public static String getDayOfMonth(Date date) {
        CALENDAR.clear();
        CALENDAR.setTime(date);
        return String.valueOf(CALENDAR.get(Calendar.DAY_OF_MONTH));
    }

    /**
     * 取得日期星期中的第几天
     *
     * @param date 日期
     * @return 第几天
     */
    public static String getDayOfWeek(Date date) {
        CALENDAR.clear();
        CALENDAR.setTime(date);
        return String.valueOf(CALENDAR.get(Calendar.DAY_OF_WEEK));
    }

    /**
     * 取得日期是年中第几周
     *
     * @param date                   日期
     * @param firstDayOfWeek         一周的第一天
     * @param minimalDaysInFirstWeek ？？
     * @return 第几周
     */
    public static int getWeekOfYear(Date date, int firstDayOfWeek, int minimalDaysInFirstWeek) {
        CALENDAR.clear();
        CALENDAR.setFirstDayOfWeek(firstDayOfWeek);
        CALENDAR.setMinimalDaysInFirstWeek(minimalDaysInFirstWeek);
        CALENDAR.setTime(date);
        return CALENDAR.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * 取得日期是年中第几周
     *
     * @param date 日期
     * @return 第几周
     */
    public static int getWeekOfYear(Date date) {
        return getWeekOfYear(date, Calendar.MONDAY, 7);
    }

    /**
     * 计算某年的总周数
     *
     * @param year 年
     * @return 周数
     */
    public static int getWeekCountOfYear(int year) {
        CALENDAR.clear();
        CALENDAR.set(year, Calendar.DECEMBER, 31, 23, 59, 59);
        return getWeekOfYear(CALENDAR.getTime());
    }

    /**
     * 取得某年某周的第一天
     *
     * @param year 年份
     * @param week 第几周
     * @return 日期
     */
    public static Date getFirstDayOfWeek(int year, int week) {
        CALENDAR.clear();
        CALENDAR.set(Calendar.YEAR, year);
        CALENDAR.set(Calendar.MONTH, Calendar.JANUARY);
        CALENDAR.set(Calendar.DATE, 1);
        CALENDAR.add(Calendar.DATE, week * 7);
        return getFirstDayOfWeek(CALENDAR.getTime());
    }

    /**
     * 取得指定日期所在周的第一天
     *
     * @param date           日期
     * @param firstDayOfWeek 一周的第一天
     * @return 日期
     */
    public static Date getFirstDayOfWeek(Date date, int firstDayOfWeek) {
        CALENDAR.clear();
        CALENDAR.setFirstDayOfWeek(firstDayOfWeek);
        CALENDAR.setTime(date);
        CALENDAR.set(Calendar.DAY_OF_WEEK, CALENDAR.getFirstDayOfWeek());
        return CALENDAR.getTime();
    }

    /**
     * 取得某年某周的最一天
     *
     * @param date 日期
     * @return 第一天的日期
     */
    public static Date getFirstDayOfWeek(Date date) {
        return getFirstDayOfWeek(date, Calendar.MONDAY);
    }

    /**
     * 取得指定日期所在周的最后一天
     *
     * @param year 年份
     * @param week 第几周
     * @return 最后一天的日期
     */
    public static Date getLastDayOfWeek(int year, int week) {
        CALENDAR.clear();
        CALENDAR.set(Calendar.YEAR, year);
        CALENDAR.set(Calendar.MONTH, Calendar.JANUARY);
        CALENDAR.set(Calendar.DATE, 1);
        CALENDAR.add(Calendar.DATE, week * 7);
        return getLastDayOfWeek(CALENDAR.getTime());
    }

    /**
     * 取得指定改日期所在周的最后一天
     *
     * @param date
     * @param firstDayOfWeek
     * @return
     */
    public static Date getLastDayOfWeek(Date date, int firstDayOfWeek) {
        CALENDAR.clear();
        CALENDAR.setFirstDayOfWeek(firstDayOfWeek);
        CALENDAR.setTime(date);
        CALENDAR.set(Calendar.DAY_OF_WEEK, CALENDAR.getFirstDayOfWeek() + 6);
        return CALENDAR.getTime();
    }

    /**
     * 取得指定日期所在周的最后一天
     *
     * @param date
     * @return
     */
    public static Date getLastDayOfWeek(Date date) {
        return getLastDayOfWeek(date, Calendar.MONDAY);
    }

    /**
     * 比较两个日期相差的天数
     *
     * @param dateStr1
     * @param dateStr2
     * @return
     */
    public static int getDayGapsBetweenDates(String dateStr1, String dateStr2) {
        return getDayGapsBetweenDates(dateStr1, dateStr2, DATE_FORMAT);
    }

    /**
     * @param dateStr1
     * @param dateStr2
     * @param format
     * @return
     */
    public static int getDayGapsBetweenDates(String dateStr1, String dateStr2, String format) {
        Date date1 = parse(dateStr1, format);
        Date date2 = parse(dateStr2, format);
        assert date1 != null;
        assert date2 != null;
        long l = date1.getTime() - date2.getTime();
        return (int) (l / (24 * 60 * 60 * 1000));
    }

    /**
     * 比较两个日期相差的月份数
     *
     * @param dateStr1
     * @param dateStr2
     * @return
     */
    public static int getMonthGapsBetweenDates(String dateStr1, String dateStr2) {
        return getMonthGapsBetweenDates(dateStr1, dateStr2, DATE_FORMAT);
    }

    /**
     * @param dateStr1
     * @param dateStr2
     * @param format
     * @return
     */
    public static int getMonthGapsBetweenDates(String dateStr1, String dateStr2, String format) {
        int month1, month2;
        Date date1 = parse(dateStr1, format);
        Date date2 = parse(dateStr2, format);
        assert date1 != null;
        assert date2 != null;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date1);
        month1 = calendar.get(Calendar.YEAR) * 12 + calendar.get(Calendar.MONTH);
        calendar.clear();
        calendar.setTime(date2);
        month2 = calendar.get(Calendar.YEAR) * 12 + calendar.get(Calendar.MONTH);
        return month1 - month2;
    }

    /**
     * 比较两个日期相差的年数
     *
     * @param dateStr1
     * @param dateStr2
     * @return
     */
    public static int getYearGapsBetweenDates(String dateStr1, String dateStr2) {
        return getYearGapsBetweenDates(dateStr1, dateStr2, DATE_FORMAT);
    }

    /**
     * @param dateStr1
     * @param dateStr2
     * @param format
     * @return
     */
    public static int getYearGapsBetweenDates(String dateStr1, String dateStr2, String format) {
        int year1, year2;
        Date date1 = parse(dateStr1, format);
        Date date2 = parse(dateStr2, format);
        assert date1 != null;
        assert date2 != null;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date1);
        year1 = calendar.get(Calendar.YEAR);
        calendar.clear();
        calendar.setTime(date2);
        year2 = calendar.get(Calendar.YEAR);
        return year1 - year2;
    }

    /**
     * 取得GregorianCalendar实例
     *
     * @param dateStr
     * @return
     */
    public static GregorianCalendar getGCalendar(String dateStr) {
        return getGCalendar(dateStr, DATETIME_FORMAT);
    }

    /**
     * @param dateStr
     * @param format
     * @return
     */
    public static GregorianCalendar getGCalendar(String dateStr, String format) {
        Date date = parse(dateStr, format);
        assert date != null;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return new GregorianCalendar(calendar.get(Calendar.YEAR),
                calendar.get(Calendar.MONTH),
                calendar.get(Calendar.DAY_OF_MONTH),
                calendar.get(Calendar.HOUR),
                calendar.get(Calendar.MINUTE),
                calendar.get(Calendar.SECOND));
    }

    /**
     * 取得GregorianCalendar实例操作日期添加，并格式化返回
     *
     * @param dateStr
     * @param value
     * @param gCalendarType
     * @return
     */
    public static String addGCalendar(String dateStr, int value, int gCalendarType) {
        return addGCalendar(dateStr, value, gCalendarType, DATETIME_FORMAT);
    }

    /**
     * 取得GregorianCalendar实例操作日期添加，并格式化返回
     *
     * @param dateStr
     * @param value
     * @param gCalendarType
     * @return
     */
    public static String addGCalendar(String dateStr, int value, int gCalendarType, String format) {
        GregorianCalendar gregorianCalendar = getGCalendar(dateStr, format);
        gregorianCalendar.add(gCalendarType, value);
        return format(gregorianCalendar.getTime(), format);
    }

    /**
     * 返回日期加X秒后的日期
     *
     * @param dateStr
     * @param value
     * @return
     */
    public static String addSecond(String dateStr, int value) {
        return addGCalendar(dateStr, value, GregorianCalendar.SECOND);
    }

    /**
     * @param dateStr
     * @param value
     * @param format
     * @return
     */
    public static String addSecond(String dateStr, int value, String format) {
        return addGCalendar(dateStr, value, GregorianCalendar.SECOND, format);
    }

    /**
     * 返回日期加X分后的日期
     *
     * @param dateStr
     * @param value
     * @return
     */
    public static String addMinute(String dateStr, int value) {
        return addGCalendar(dateStr, value, GregorianCalendar.MINUTE);
    }

    /**
     * @param dateStr
     * @param value
     * @param format
     * @return
     */
    public static String addMinute(String dateStr, int value, String format) {
        return addGCalendar(dateStr, value, GregorianCalendar.MINUTE, format);
    }

    /**
     * 返回日期加X小时后的日期
     *
     * @param dateStr
     * @param value
     * @return
     */
    public static String addHour(String dateStr, int value) {
        return addGCalendar(dateStr, value, GregorianCalendar.HOUR);
    }

    /**
     * @param dateStr
     * @param value
     * @param format
     * @return
     */
    public static String addHour(String dateStr, int value, String format) {
        return addGCalendar(dateStr, value, GregorianCalendar.HOUR, format);
    }

    /**
     * 返回日期加X天后的日期
     *
     * @param dateStr
     * @param value
     * @return
     */
    public static String addDay(String dateStr, int value) {
        return addGCalendar(dateStr, value, GregorianCalendar.DATE);
    }

    /**
     * @param dateStr
     * @param value
     * @param format
     * @return
     */
    public static String addDay(String dateStr, int value, String format) {
        return addGCalendar(dateStr, value, GregorianCalendar.DATE, format);
    }

    /**
     * 返回日期加X月后的日期
     *
     * @param dateStr
     * @param value
     * @return
     */
    public static String addMonth(String dateStr, int value) {
        return addGCalendar(dateStr, value, GregorianCalendar.MONTH);
    }

    /**
     * 返回日期加X年后的日期
     *
     * @param dateStr
     * @param value
     * @return
     */
    public static String addYear(String dateStr, int value) {
        return addGCalendar(dateStr, value, GregorianCalendar.YEAR);
    }

    /**
     * 添加年份
     *
     * @param dateStr
     * @param value
     * @param format
     * @return
     */
    public static String addYear(String dateStr, int value, String format) {
        return addGCalendar(dateStr, value, GregorianCalendar.YEAR, format);
    }

    /**
     * 日期字符串装为日期
     *
     * @param dateStr
     * @param format
     * @return
     */
    public static Date parse(String dateStr, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        try {
            return simpleDateFormat.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 默认格式转换日期
     *
     * @param dateStr
     * @return
     */
    public static Date parse(String dateStr) {
        return parse(dateStr, DATETIME_FORMAT);
    }

    /**
     * 日期格式化
     *
     * @param date
     * @param format
     * @return
     */
    public static String format(Date date, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(date);
    }

    /**
     * 默认格式格式化日期
     *
     * @param date
     * @return
     */
    public static String format(Date date) {
        return format(date, DATETIME_FORMAT);
    }

    /**
     * 年份是否为闰年
     *
     * @param year
     * @return
     */
    public static boolean isLeap(int year) {
        return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
    }

    /**
     * 获取知道日期 的零点、24点
     * time = 0 零点 time = 24 24点
     * @return
     */
    public static Date zeroTime(Integer time, Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, time);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date zeroTime = calendar.getTime();
        return zeroTime;
    }
}
